package ch.ethz.fcl.metrobuzz.render.accessbility;

import java.util.List;

import org.lwjgl.opengl.GL11;

import ch.ethz.fcl.metrobuzz.MBContainer;
import ch.ethz.fcl.metrobuzz.MBProperty;
import ch.ethz.fcl.metrobuzz.algorithm.network.shortest_path.public_transport.Walk;
import ch.ethz.fcl.metrobuzz.data.accessibility.activity.PointOfInterest;
import ch.ethz.fcl.metrobuzz.data.transit.Stop;
import ch.ethz.fcl.metrobuzz.render.accessbility.interaction.AcceGlobalPanel;
import ch.ethz.fcl.metrobuzz.render.accessbility.interaction.AcceKeyAction;
import ch.ethz.fcl.metrobuzz.render.accessbility.interaction.AcceLocalPanel;
import ch.ethz.fcl.metrobuzz.render.accessbility.interaction.AcceMouseAction;
import ch.ethz.fcl.metrobuzz.render.accessbility.interaction.AcceTimeScalePanel;
import ch.ethz.fcl.metrobuzz.render.accessbility.view.RoadEfficiencyView;
import ch.ethz.fcl.metrobuzz.render.accessbility.view.global.AccessibilityMapView;
import ch.ethz.fcl.metrobuzz.render.accessbility.view.local.FlowMapView;
import ch.ethz.fcl.metrobuzz.render.accessbility.view.local.IsochroneView;
import ch.ethz.fcl.metrobuzz.render.accessbility.view.od.ODTemporalChangeView;
import ch.ethz.fcl.metrobuzz.render.accessbility.view.time_scale.TimeScaledMap;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Point2D;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Rectangle;
import ch.ethz.fcl.metrobuzz.tools.MBGL;

public class AccessibilityRender {
	private MBContainer container;
	private AcceMouseAction mouseAction = null;

	private RoadEfficiencyView roadEffiView = null;
	private FlowMapView flowMapView = null;

	private IsochroneView isoView = null;
	private AccessibilityMapView acceMap = null;

	private ODTemporalChangeView odView = null;

	private List<Stop> stops;

	private AcceGlobalPanel globalPanel;
	private AcceLocalPanel localPanel;

	public static boolean ACCESSIBILITY_MAP_VIEW = false;
	public static boolean ROAD_EFFICIENCY_VIEW = true;

	public static boolean FLOW_MAP_VIEW = false;
	public static boolean ISOCHRONE_VIEW = false;

	private AcceTimeScalePanel timeScalePanel;
	public static boolean TIME_SCALED_VIEW = false;
	private TimeScaledMap timeScaledMap;

	public AccessibilityRender(MBContainer container) {
		this.container = container;
		stops = container.getData().getPublicTransit().getStops();

		mouseAction = new AcceMouseAction(this.container, this);

		roadEffiView = new RoadEfficiencyView(this.container, this);
		flowMapView = new FlowMapView(this.container, this);
		isoView = new IsochroneView(this.container, this);
		acceMap = new AccessibilityMapView(this.container);

		timeScaledMap = new TimeScaledMap(this.container, this);

		this.odView = new ODTemporalChangeView(container, this);

		globalPanel = new AcceGlobalPanel();
		localPanel = new AcceLocalPanel();
		timeScalePanel = new AcceTimeScalePanel();
	}

	public void update() {
		roadEffiView.update();
		flowMapView.update();
		isoView.update();
	}

	public void render() {
		MBGL.enableBlend();

		float cameraDist = container.getViewer().getCamera().getDistance();
		if (AcceKeyAction.showStops && cameraDist <= 0.8f)
			renderStops();

		if (TIME_SCALED_VIEW && mouseAction.getOrigin() != null) {
			timeScaledMap.render();
		} else {
			if (mouseAction.getOrigin() == null
					|| mouseAction.getDestination() == null) {
				if (ACCESSIBILITY_MAP_VIEW) {
					acceMap.render();
				} else if (ROAD_EFFICIENCY_VIEW) {
					roadEffiView.render();
				} else if (mouseAction.getOrigin() != null) {
					if (ISOCHRONE_VIEW)
						isoView.renderInBound();

					if (FLOW_MAP_VIEW)
						flowMapView.render();

					if (ISOCHRONE_VIEW)
						isoView.renderOutLine();

					flowMapView.renderODStop(mouseAction.getOrigin());
				}
			} else {
				container.getData().getRoadNetwork().render();
				odView.render();
			}
		}
		if (MBProperty.ACTIVITY && AcceKeyAction.showActivities)
			renderActivity(container.getData().getActivity().getWork());

		MBGL.disableBlend();
	}

	private void renderStops() {
		GL11.glPointSize(2);

		GL11.glColor4f(0.2f, 0.2f, 0.2f, 0.2f);
		GL11.glBegin(GL11.GL_POINTS);
		for (Stop s : stops) {
			if (s.getPassingRoutes().size() == 0)
				continue;

			Point2D p = s.toPoint();
			if (p != null)
				GL11.glVertex3f(p.getX(), p.getY(), 0);
		}
		GL11.glEnd();

	}

	/**
	 * render the activities as blue points
	 */
	public void renderActivity(List<PointOfInterest> pois) {
		GL11.glColor4f(0.0f, 0.1f, 0.8f, 1);
		GL11.glPointSize(2.0f);
		GL11.glBegin(GL11.GL_POINTS);

		for (PointOfInterest poi : pois)
			GL11.glVertex2f(poi.getX(), poi.getY());

		GL11.glEnd();

		float length = container.getViewer().getProjection()
				.getWorldDistance(6);
		GL11.glLineWidth(1.0f);

		for (PointOfInterest poi : pois) {
			float minX = poi.getX() - length / 2;
			float maxX = poi.getX() + length / 2;

			float minY = poi.getY() - length / 2;
			float maxY = poi.getY() + length / 2;

			Rectangle rec = new Rectangle(minX, minY, maxX, maxY);

			rec.render(GL11.GL_LINE_STRIP);
		}
	}

	public FlowMapView getFlowMapView() {
		return flowMapView;
	}

	public AcceMouseAction getMouseAction() {
		return mouseAction;
	}

	public IsochroneView getIsochroneView() {
		return isoView;
	}

	public AcceGlobalPanel getGlobalPanel() {
		return globalPanel;
	}

	public AcceTimeScalePanel getTimeScaledPanel() {
		return timeScalePanel;
	}

	public AcceLocalPanel getLocalPanel() {
		return localPanel;
	}
}
